const MyPromise = require("../template.js")

/** 十二、Promise.finally 测试 */

// 测试 1: finally 在成功后执行
function testFinallyAfterSuccess() {
  let finallyCalled = false

  MyPromise.resolve(1)
    .finally(() => {
      finallyCalled = true
    })
    .then((value) => {
      console.log("12.1 Finally after success - value:", value === 1)
      console.log("12.2 Finally after success - called:", finallyCalled === true)
    })
}

// 测试 2: finally 在失败后执行
function testFinallyAfterReject() {
  let finallyCalled = false

  MyPromise.reject("Error")
    .finally(() => {
      finallyCalled = true
    })
    .catch((reason) => {
      console.log("12.3 Finally after reject - reason:", reason === "Error")
      console.log("12.4 Finally after reject - called:", finallyCalled === true)
    })
}

// 测试 3: finally 不改变成功的值
function testFinallyNotChangeValue() {
  MyPromise.resolve(42)
    .finally(() => {
      return 100 // 返回值应该被忽略
    })
    .then((value) => console.log("12.5 Finally not change value:", value === 42))
}

// 测试 4: finally 不改变失败的原因
function testFinallyNotChangeReason() {
  MyPromise.reject("Original Error")
    .finally(() => {
      return "Something" // 返回值应该被忽略
    })
    .catch((reason) => console.log("12.6 Finally not change reason:", reason === "Original Error"))
}

// 测试 5: finally 中抛出错误会覆盖原结果
function testFinallyThrowError() {
  MyPromise.resolve(1)
    .finally(() => {
      throw new Error("Finally Error")
    })
    .catch((reason) => console.log("12.7 Finally throw error:", reason.message === "Finally Error"))
}

// 测试 6: finally 返回 rejected Promise 会覆盖原结果
function testFinallyReturnRejected() {
  MyPromise.resolve(1)
    .finally(() => {
      return MyPromise.reject("Finally Reject")
    })
    .catch((reason) => console.log("12.8 Finally return rejected:", reason === "Finally Reject"))
}

// 测试 7: finally 返回 Promise 需要等待
function testFinallyReturnPromise() {
  let order = ""

  MyPromise.resolve(1)
    .finally(() => {
      return new MyPromise((resolve) => {
        setTimeout(() => {
          order += "1"
          resolve()
        }, 50)
      })
    })
    .then((value) => {
      order += "2"
      console.log("12.9 Finally return promise - value:", value === 1)
      console.log("12.10 Finally return promise - order:", order === "12")
    })
}

// 测试 8: finally 无参数
function testFinallyNoArgs() {
  MyPromise.resolve(1)
    .finally((value) => {
      console.log("12.11 Finally no args:", value === undefined)
    })
    .then((value) => console.log("12.12 Finally no args - value:", value === 1))
}

// 测试 9: 链式 finally
function testFinallyChain() {
  let count = 0

  MyPromise.resolve(1)
    .finally(() => {
      count++
    })
    .finally(() => {
      count++
    })
    .then((value) => {
      console.log("12.13 Finally chain - value:", value === 1)
      console.log("12.14 Finally chain - count:", count === 2)
    })
}

// 测试 10: finally 在失败时返回成功的 Promise（不改变拒绝）
function testFinallyReturnResolveOnReject() {
  MyPromise.reject("Error")
    .finally(() => {
      return MyPromise.resolve("Should be ignored")
    })
    .catch((reason) => console.log("12.15 Finally resolve on reject:", reason === "Error"))
}

// 测试 11: finally 中返回 thenable
function testFinallyReturnThenable() {
  const thenable = {
    then: (resolve) => {
      setTimeout(() => resolve(), 30)
    }
  }

  MyPromise.resolve(42)
    .finally(() => {
      return thenable
    })
    .then((value) => console.log("12.16 Finally return thenable:", value === 42))
}

// 测试 12: finally 覆盖成功为失败
function testFinallyOverrideSuccessWithError() {
  MyPromise.resolve("Success")
    .finally(() => {
      throw new Error("Override")
    })
    .then(
      (value) => console.log("12.17 Finally override success:", false),
      (reason) => console.log("12.17 Finally override success:", reason.message === "Override")
    )
}

testFinallyAfterSuccess()
testFinallyAfterReject()
testFinallyNotChangeValue()
testFinallyNotChangeReason()
testFinallyThrowError()
testFinallyReturnRejected()
testFinallyReturnPromise()
testFinallyNoArgs()
testFinallyChain()
testFinallyReturnResolveOnReject()
testFinallyReturnThenable()
testFinallyOverrideSuccessWithError()
